package com.kevin.spider.service;

import cn.hutool.core.io.FileUtil;
import com.kevin.spider.domain.bo.SpiderContext;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import com.ruoyi.common.utils.CollectionUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 张帆
 * @date 2025/6/18 11:19
 */
@Slf4j
public class BaseSpiderService {
    @SneakyThrows
    public SpiderContext buildSpiderContext() {
        SpiderContext spiderContext = new SpiderContext();
        Playwright playwright = Playwright.create();

        // 2. 上下文配置
        Map<String, String> headers = new HashMap<>();

        //   headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        //   headers.put("Accept-Encoding", "gzip, deflate, br");
        //   headers.put("Accept-Language", "zh-CN,zh;q=0.9");
        //   headers.put("Cache-Control", "no-cache");
        //   headers.put("Connection", "keep-alive");
        //   headers.put("Pragma", "no-cache");
        //   headers.put("Upgrade-Insecure-Requests", "1");


        BrowserType.LaunchPersistentContextOptions options = new BrowserType.LaunchPersistentContextOptions()
                .setHeadless(false)
                .setIgnoreHTTPSErrors(true)
                .setViewportSize(1800, 900)
                .setAcceptDownloads(true)
                .setJavaScriptEnabled(true)
                .setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                .setLocale("zh-CN")
                .setExtraHTTPHeaders(headers)
                .setDeviceScaleFactor(1.0)
                // 全局操作延迟
                .setSlowMo(500);


        File playwrightDataDir = FileUtil.file(FileUtil.getTmpDir(), "playwright_data");
        log.info("playwrightDataDir:{}", playwrightDataDir.getAbsolutePath());
        if (!FileUtil.exist(playwrightDataDir)) {
            FileUtil.mkdir(playwrightDataDir);
        }
        Path userDataDir = playwrightDataDir.toPath();

        BrowserContext context = playwright.chromium().launchPersistentContext(
                userDataDir, options
        );

        // 注入初始化脚本
        context.addInitScript("Object.defineProperty(navigator, 'webdriver', { get: () => undefined })");
        context.addInitScript("""
                 // 核心自动化标识隐藏
                 Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
                 Object.defineProperty(window, 'chrome', { get: () => undefined });
                 delete navigator.__proto__.webdriver;
                
                 // 修改语言和时区
                 Object.defineProperty(navigator, 'language', { get: () => 'zh-CN' });
                 Object.defineProperty(navigator, 'languages', { get: () => ['zh-CN', 'zh'] });
                 Object.defineProperty(Intl, 'DateTimeFormat', () => {});
                
                 // 修改屏幕属性
                 Object.defineProperty(screen, 'width', { get: () => 1920 });
                 Object.defineProperty(screen, 'height', { get: () => 1080 });
                 Object.defineProperty(screen, 'availWidth', { get: () => 1920 });
                 Object.defineProperty(screen, 'availHeight', { get: () => 1040 });
                 Object.defineProperty(screen, 'colorDepth', { get: () => 24 });
                
                 // 修改硬件属性
                 Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => 4 });
                 Object.defineProperty(navigator, 'deviceMemory', { get: () => 8 });
                
                 // 修改插件信息
                 Object.defineProperty(navigator, 'plugins', {\s
                     get: () => [1, 2, 3, 4, 5].map(() => ({
                         name: 'Chrome PDF Viewer',
                         filename: 'internal-pdf-viewer',
                         description: 'Portable Document Format'
                     }))
                 });
                
                 // WebGL指纹伪装
                 const getParameter = WebGLRenderingContext.prototype.getParameter;
                 WebGLRenderingContext.prototype.getParameter = function(parameter) {
                     if (parameter === 37445) return 'Intel Inc.'; // UNMASKED_VENDOR_WEBGL
                     if (parameter === 37446) return 'Intel Iris OpenGL Engine'; // UNMASKED_RENDERER_WEBGL
                     return getParameter.call(this, parameter);
                 };
                
                 // Canvas指纹干扰
                 HTMLCanvasElement.prototype.toDataURL = function() {
                     return '';
                 };
                
                 // 禁用WebRTC
                 Object.defineProperty(window, 'RTCPeerConnection', { get: () => undefined });
                 Object.defineProperty(window, 'webkitRTCPeerConnection', { get: () => undefined });
                 Object.defineProperty(window, 'mozRTCPeerConnection', { get: () => undefined });
                """);
        context.setDefaultNavigationTimeout(30000);
        context.setDefaultTimeout(60000);
        Page page = CollectionUtils.getFirst(context.pages());

        spiderContext.setPlaywright(playwright);
        spiderContext.setBrowserContext(context);
        spiderContext.setPage(page);
        return spiderContext;
    }
}
